package cn.xiongxf.exception;

import cn.xiongxf.result.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 全局异常处理器
 */
@RestControllerAdvice  // 全局统一异常注解，@RestController的增强，可以在controller执行前后做额外逻辑
@Slf4j  // 日志器注解
public class GlobalExceptionHandler {

    // 捕捉指定的异常，哪种异常先出现，就捕捉到哪种(前提是controller的包名和当前类的包名一致)
    @ExceptionHandler(value = Exception.class)
    public JsonResult systemException(Exception e,HttpServletRequest request){
        e.printStackTrace();
        // 打印日志   {}表示占位符
        log.error("发生系统异常！ 请求路径：{}, 异常信息：{}",request.getRequestURI(),e.getMessage());
        // 返回异常信息

        // AccessDeniedException异常
        if (e.getClass().getSimpleName().equals("AccessDeniedException")){
            return JsonResult.error("无访问权限！");
        }

        return JsonResult.error(GlobalErrorCode.SERVICE_ERROR);
    }

    @ExceptionHandler(value = GlobalCustomException.class)
    public JsonResult customException(GlobalCustomException e, HttpServletRequest request){
        e.printStackTrace();
        // 打印日志
//        log.error("发生业务异常！ 请求路径：{}, 异常码：{}, 异常信息：{}" ,request.getRequestURI(),e.getErrorCode(),e.getErrorMessage());
        log.error("发生业务异常！ 请求路径：{}, 异常信息：{}" ,request.getRequestURI(),e.getMessage());
        // 返回异常信息
//        return JsonResult.error(e.getErrorCode(),e.getErrorMessage());
        return JsonResult.error(e.getMessage());
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public JsonResult methodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request){
        e.printStackTrace();  // 在此打断点，分析MethodArgumentNotValidException的结构组成
        // 使用StringBuilder拼接异常信息
        StringBuilder sb = new StringBuilder();
        sb.append("参数校验失败：");
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        for (ObjectError error : errors) {
            String defaultMessage = error.getDefaultMessage();
            sb.append(defaultMessage).append("；");
        }
        // 打印日志
        log.error("发生方法参数校验异常！ 请求路径：{},  异常信息：{}" ,request.getRequestURI(),sb);
        // 返回异常信息
        return JsonResult.error(sb.toString());
    }
}
